﻿using Microsoft.Xna.Framework;
using Newtonsoft.Json;
using PlaceholderAPI;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Timers;
using TerrariaApi.Server;
using TShockAPI;
using TShockAPI.Hooks;

namespace BuffPrefixV2
{
    [ApiVersion(2,1)]
    public class Main : TerrariaPlugin
    {
        public override string Name => "BuffPrefix";

        public override Version Version => Assembly.GetExecutingAssembly().GetName().Version;

        public override string Author => "豆沙";

        public override string Description => "一款可以赋予Buff的称号插件";
        public Main(Terraria.Main game) : base(game){}
        public static List<Prefix> prefixes = new List<Prefix>();
        public static List<PrefixPlayer> players = new List<PrefixPlayer>();
        public static string pluginPrefix = "[c/02DF82:[][c/00E3E3:BuffPrefix][c/02DF82:]]";
        public static Timer timer = new Timer(1000);
        public override void Initialize()
        {
            Register();
            ServerApi.Hooks.ServerJoin.Register(this, OnJoin);
            ServerApi.Hooks.ServerChat.Register(this, OnChat);
            ServerApi.Hooks.GamePostInitialize.Register(this, OnPostInitialize);
            PlaceholderAPI.Hooks.PreGetText += OnGetText;
            GeneralHooks.ReloadEvent += OnReload;
            timer.Elapsed += OnElapsed;
            ConfigUtils.ReadConfig();
        }

        private void OnGetText(Hooks.GetTextArgs args)
        {
            var tsplr = args.Player;
            var bplr = players.Find(p=>p.Name==tsplr.Name);
            if (bplr!=null)
            {
                args.List["{prefixName}"] = GetPrefix(bplr.CurrentPrefixID).PrefixName;
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                
                ServerApi.Hooks.ServerJoin.Deregister(this, OnJoin);
                ServerApi.Hooks.ServerChat.Deregister(this, OnChat);
                ServerApi.Hooks.GamePostInitialize.Deregister(this, OnPostInitialize);
                GeneralHooks.ReloadEvent -= OnReload;
                ConfigUtils.UpdateConfig();
                timer.Elapsed -= OnElapsed;
                timer.Stop();

            }
            base.Dispose(disposing);
        }
        private void Register() 
        {
            PlaceholderAPI.PlaceholderAPI.Instance.placeholderManager.Register("{prefixName}"); 
        }
        private void OnReload(ReloadEventArgs e)
        {
            prefixes = DBManager.GetAllPrefixes();
            players = DBManager.GetAllPrefixPlayers();
            ConfigUtils.ReadConfig();
            e.Player.SendSuccessMessage(pluginPrefix+"插件重载完成！");
        }
        private void OnPostInitialize(EventArgs args)
        {
            //数据表的添加
            DBManager.CreatePlayersTable();
            DBManager.CreatePrefixesTable();
            //指令添加
            Commands.ChatCommands.Add(new Command("bp.user", BP, "bp") { AllowServer=false});
            Commands.ChatCommands.Add(new Command("bp.admin", BPAdmin, "bpadmin"));
            //数据加载
            players = DBManager.GetAllPrefixPlayers();
            prefixes = DBManager.GetAllPrefixes();
            //计时器启动
            timer.Start();
        }

        private void OnElapsed(object sender, ElapsedEventArgs e)
        {
            if (players.Count!=0)
            {
                foreach (var plr in players)
                {
                    TSPlayer tsplr;
                    if (TSPlayer.FindByNameOrID(plr.Name).Count!=0)
                    {
                        tsplr = TSPlayer.FindByNameOrID(plr.Name)[0];
                        if (tsplr.Active  && tsplr.ConnectionAlive  && tsplr != null)
                        {
                            var prefix = GetPrefix(plr.CurrentPrefixID);
                            if (prefix.BuffList.Count != 0)
                            {
                                for (int i = 0; i < prefix.BuffList.Count; i++)
                                {
                                    tsplr.SetBuff(prefix.BuffList[i], 3600);
                                }
                            }
                        }
                    }
                }
            }
        }

        private void BPAdmin(CommandArgs args)//BP管理员指令
        {
            if (args.Parameters.Count<1)
            {
                args.Player.SendInfoMessage("指令错误！请键入/bpadmin help 查看帮助");
                return;
            }
            int prefixID = 0;
            int buffID = 0;
            string stringText = "";
            PrefixPlayer pplr = null;
            Prefix prefix = null;
            var dbPlr = DBManager.GetPrefixPlayer(stringText);
            switch (args.Parameters[0])
            {
                case "help":
                    if (args.Parameters.Count == 2&& args.Parameters[1] == "2")
                    {
                        StringBuilder helpText_2 = new StringBuilder();
                        helpText_2.AppendLine("/bpadmin addbuff [称号ID] [BuffID] 给称号添加Buff");
                        helpText_2.AppendLine("/bpadmin delbuff [称号ID] [BuffID] 删除称号的Buff");
                        helpText_2.AppendLine("/bpadmin remove [称号ID] 移除称号");
                        helpText_2.AppendLine("/bpadmin list 列出所有的称号");
                        args.Player.SendInfoMessage(helpText_2.ToString());
                        return;
                    }
                    StringBuilder helpText_1 = new StringBuilder();
                    helpText_1.AppendLine("/bpadmin create [称号名称] 创建一个称号");
                    helpText_1.AppendLine("/bpadmin give [称号ID] [玩家名称] 将称号给予玩家");
                    helpText_1.AppendLine("/bpadmin take [称号ID] [玩家名称] 取走玩家的称号");
                    helpText_1.AppendLine("/bpadmin help 2 进行翻页");
                    args.Player.SendInfoMessage(helpText_1.ToString());   
                    break;
                case "list":
                    StringBuilder prefixesListString = new StringBuilder();
                    if (prefixes.Count!=0)
                    {
                        foreach (var buffPrefix in prefixes)
                        {
                            prefixesListString.AppendLine($"{buffPrefix.ID}:{buffPrefix.PrefixName}"); 
                        }
                    }
                    args.Player.SendInfoMessage(prefixesListString.ToString());
                    break;
                case "create":
                    if (args.Parameters.Count == 1 || args.Parameters.Count > 2 || string.IsNullOrEmpty(args.Parameters[1]))
                    {
                        args.Player.SendErrorMessage(pluginPrefix+" 语法错误,正确语法:/bpadmin create [称号名字]");
                        return;
                    }
                    prefix = new Prefix(GetMaxID(prefixes) + 1, args.Parameters[1], new List<int>());
                    prefixes.Add(prefix);
                    DBManager.AddPrefix(prefix);
                    args.Player.SendSuccessMessage(pluginPrefix + " 称号创建成功");
                    break;
                case "give":
                    if (args.Parameters.Count>3||(args.Parameters.Count>=1&&args.Parameters.Count<=2))
                    {
                        args.Player.SendErrorMessage(pluginPrefix + " 语法错误,正确语法:/bpadmin give [称号ID] [玩家名字]");
                        return;
                    }
                    stringText = args.Parameters[2];
                    pplr = players.Find(p=>p.Name==stringText);
                    if (int.TryParse(args.Parameters[1], out prefixID))
                    {
                        if (pplr == null)
                        {
                            if (dbPlr != null)
                            {
                                if (dbPlr.AddPrefix(prefixID))
                                {
                                    args.Player.SendSuccessMessage(pluginPrefix + " 成功给予玩家称号");
                                }
                                else
                                {
                                    args.Player.SendErrorMessage(pluginPrefix + " 玩家已存在该称号");
                                }
                            }
                            else
                            {
                                args.Player.SendErrorMessage(pluginPrefix + " 玩家不存在");
                            }
                        }
                        else
                        {
                            if (pplr.AddPrefix(prefixID))
                            {
                                args.Player.SendSuccessMessage(pluginPrefix + " 成功给予玩家称号");
                            }
                            else {
                                args.Player.SendErrorMessage(pluginPrefix + " 玩家已存在该称号");
                            }      
                        }
                    }
                    else {
                        args.Player.SendErrorMessage(pluginPrefix + " 请输入正确的数字");
                    }          
                    break;
                case "take":
                    if (args.Parameters.Count > 3 || (args.Parameters.Count >= 1 && args.Parameters.Count <= 2))
                    {
                        args.Player.SendErrorMessage(pluginPrefix + " 语法错误,正确语法:/bpadmin take [称号ID] [玩家名字]");
                        return;
                    }
                    stringText = args.Parameters[2];
                    pplr = players.Find(p => p.Name == stringText);
                    if (int.TryParse(args.Parameters[1], out prefixID))
                    {
                        if (pplr == null)
                        {
                            if (dbPlr != null)
                            {
                                if (dbPlr.CurrentPrefixID == prefixID)//检测玩家当前是否佩戴要删除的称号
                                {
                                    dbPlr.CurrentPrefixID = ConfigUtils.config.DefaultPrefix.ID;
                                }
                                if (dbPlr.DelPrefix(prefixID))
                                {
                                    args.Player.SendSuccessMessage(pluginPrefix + " 成功取走玩家称号");
                                }
                                else
                                {
                                    args.Player.SendErrorMessage(pluginPrefix + " 玩家不存在该称号");
                                }
                            }
                            else
                            {
                                args.Player.SendErrorMessage(pluginPrefix + " 玩家不存在");
                            }
                        }
                        else
                        {
                            if (pplr.CurrentPrefixID==prefixID)//检测玩家当前是否佩戴要删除的称号
                            {
                                pplr.CurrentPrefixID = ConfigUtils.config.DefaultPrefix.ID;
                            }
                            if (pplr.DelPrefix(prefixID))
                            {
                                args.Player.SendSuccessMessage(pluginPrefix + " 成功取走玩家称号");
                            }
                            else
                            {
                                args.Player.SendErrorMessage(pluginPrefix + " 玩家不存在该称号");
                            }
                        }
                    }
                    else
                    {
                        args.Player.SendErrorMessage(pluginPrefix + " 请输入正确的数字");
                    }
                    break;
                case "addbuff":
                    if (args.Parameters.Count > 3 || (args.Parameters.Count >= 1 && args.Parameters.Count <= 2))
                    {
                        args.Player.SendErrorMessage(pluginPrefix + " 语法错误,正确语法:/bpadmin addbuff [称号ID] [BuffID]");
                        return;
                    }
                    if (int.TryParse(args.Parameters[1], out prefixID) && prefixID > 0)
                    {
                        prefix = GetPrefix(prefixID);
                        if (prefix != null)
                        {
                            if (int.TryParse(args.Parameters[2], out buffID) && buffID >= 1 && buffID <= 322)
                            {
                                if (prefix.AddBuff(buffID))
                                {
                                    args.Player.SendSuccessMessage(pluginPrefix + " 成功添加Buff效果");
                                }
                                else
                                {
                                    args.Player.SendErrorMessage(pluginPrefix + " Buff效果已存在");
                                }
                            }
                            else
                            {
                                args.Player.SendErrorMessage(pluginPrefix + " 请输入正确的数字（大于等于1小于等于322）");
                            }
                        }
                        else
                        {
                            args.Player.SendErrorMessage(pluginPrefix + " 称号不存在");
                        }
                    }
                    else 
                    {
                        args.Player.SendErrorMessage(pluginPrefix + " 请输入正确的数字");
                    }
                    break;
                case "delbuff":
                    if (args.Parameters.Count > 3 || (args.Parameters.Count >= 1 && args.Parameters.Count <= 2))
                    {
                        args.Player.SendErrorMessage(pluginPrefix + " 语法错误,正确语法:/bpadmin delbuff [称号ID] [BuffID]");
                        return;
                    }
                    if (int.TryParse(args.Parameters[1], out prefixID) && prefixID > 0)
                    {
                        prefix = GetPrefix(prefixID);
                        if (prefix != null)
                        {
                            if (int.TryParse(args.Parameters[2], out buffID) && buffID >= 1 && buffID <= 322)
                            {
                                if (prefix.DelBuff(buffID))
                                {
                                    args.Player.SendSuccessMessage(pluginPrefix + " 成功删除Buff效果");
                                }
                                else
                                {
                                    args.Player.SendErrorMessage(pluginPrefix + " Buff效果不存在");
                                }
                            }
                            else
                            {
                                args.Player.SendErrorMessage(pluginPrefix + " 请输入正确的数字（大于等于1小于等于322）");
                            }
                        }
                        else
                        {
                            args.Player.SendErrorMessage(pluginPrefix + " 称号不存在");
                        }
                    }
                    else
                    {
                        args.Player.SendErrorMessage(pluginPrefix + " 请输入正确的数字");
                    }
                    break;
                case "remove":
                    if (args.Parameters.Count > 2 )
                    {
                        args.Player.SendErrorMessage(pluginPrefix + " 语法错误,正确语法:/bpadmin remove [称号ID]");
                        return;
                    }
                    if (int.TryParse(args.Parameters[1], out prefixID) && prefixID > 0)
                    {
                        prefix = GetPrefix(prefixID);
                        if (prefix != null)
                        {
                            prefixes.Remove(prefix);
                            DBManager.DeletePrefix(prefix.ID);
                            args.Player.SendSuccessMessage(pluginPrefix + " 成功删除称号");
                        }
                        else 
                        {
                            args.Player.SendErrorMessage("称号不存在");
                        }
                    }
                    else {
                        args.Player.SendErrorMessage(pluginPrefix+" 请输入正确的数字");
                    }
                    break;
                default:
                    args.Player.SendInfoMessage(pluginPrefix+" 指令错误！请键入/bp help 查看帮助");
                    break;
            }
        }

        private void BP(CommandArgs args)//BP用户指令
        {
            if (args.Parameters.Count < 1)
            {
                args.Player.SendInfoMessage(pluginPrefix+" 指令错误！请键入/bp help 查看帮助");
                return;
            }
            if (args.Player.RealPlayer==false)
            {
                args.Player.SendInfoMessage(pluginPrefix + " 你必须在游戏中使用此命令");
                return;
            }
            int prefixID = 0;
            PrefixPlayer plr = players.Find(p=>p.Name==args.Player.Name);
            if (plr == null)
            {
                plr = DBManager.GetPrefixPlayer(args.Player.Name);
                if (plr==null)
                {
                    args.Player.SendErrorMessage(pluginPrefix + " 数据出错，无法使用指令");
                    return;
                }
            }    
            switch (args.Parameters[0])
            {
                case "help":
                    StringBuilder helpText = new StringBuilder();
                    helpText.AppendLine("/bp help 查看帮助");
                    helpText.AppendLine("/bp switch [称号ID] 穿戴称号");
                    helpText.AppendLine("/bp me 查看当前称号信息");
                    helpText.AppendLine("/bp list 查看称号仓库");
                    helpText.AppendLine("/bp takeoff 脱下称号");
                    args.Player.SendInfoMessage(helpText.ToString());
                    break;
                case "switch":
                    if (int.TryParse(args.Parameters[1], out prefixID) && prefixID > 0)
                    {
                        if (plr.IsOwned(prefixID))
                        {
                            plr.CurrentPrefixID = prefixID;
                            DBManager.UpdatePrefixPlayer(plr);
                            args.Player.SendSuccessMessage(pluginPrefix + " 佩戴成功");
                        }
                        else {
                            args.Player.SendErrorMessage(pluginPrefix + " 未拥有该称号");
                        }
                    }
                    else {
                        args.Player.SendSuccessMessage(pluginPrefix+" 请输入正确的数字");
                    }
                    break;
                case "list":
                    StringBuilder prefixList = new StringBuilder();
                    if (plr!=null&&plr.PrefixPossessions.Count!=0)
                    {
                        foreach (var id in plr.PrefixPossessions)
                        {
                            var prefix = GetPrefix(id);
                            if (prefix!=null)
                                prefixList.AppendLine($"{prefix.ID}:{prefix.PrefixName}");
                        }
                    }
                    args.Player.SendInfoMessage(prefixList.ToString());
                    break;
                case "takeoff":
                    plr.CurrentPrefixID = ConfigUtils.config.DefaultPrefix.ID;
                    DBManager.UpdatePrefixPlayer(plr);
                    args.Player.SendSuccessMessage(pluginPrefix+" 成功脱下称号");
                    break;
                case "me":
                    var prefix_me = GetPrefix(plr.CurrentPrefixID);
                    StringBuilder meInfo = new StringBuilder();
                    meInfo.AppendLine("称号信息如下:");
                    meInfo.AppendLine($"称号ID:{prefix_me.ID}");
                    meInfo.AppendLine($"称号名称:{prefix_me.PrefixName}");
                    meInfo.AppendLine($"Buff列表:{JsonConvert.SerializeObject(prefix_me.BuffList)}");
                    args.Player.SendInfoMessage(meInfo.ToString());
                    break;
                default:
                    args.Player.SendInfoMessage(pluginPrefix+" 指令错误！请键入/bp help 查看帮助");
                    break;
            }
        }

        private void OnChat(ServerChatEventArgs args)
        {
            /*if (ConfigUtils.config.API) return;
            if (args.Text.IndexOf(TShock.Config.Settings.CommandSilentSpecifier) == 0 ||
                      args.Text.IndexOf(TShock.Config.Settings.CommandSpecifier) == 0) return;
            var tsplr = TShock.Players[args.Who];
            var plr = players.Find(p=>p.Name==tsplr.Name);
            var prefix = GetPrefix(plr.CurrentPrefixID);
            args.Handled = true;*/
        }
 

        private void OnJoin(JoinEventArgs args)
        {
            var plr = TShock.Players[args.Who];
            var pplr = players.Find(p=>p.Name==plr.Name);
            if (pplr == null)
            {
                pplr = new PrefixPlayer(plr.Name, ConfigUtils.config.DefaultPrefix.ID, new List<int>());
                DBManager.AddPrefixPlayer(pplr);
                TShock.Log.ConsoleInfo($"[BuffPrefix] 玩家 {plr.Name} 数据添加成功");
                players.Add(pplr);
            }


            /*if (pplr == null)
            {
                pplr = new PrefixPlayer(players.Count + 1, plr.Name, ConfigUtils.config.DefaultPrefix.ID, new List<int>());
                DBManager.AddPrefixPlayer(pplr);//数据库添加玩家信息
                TShock.Log.ConsoleInfo($"[BuffPrefix] 玩家 {plr.Name} 数据添加成功");
            }
            players.Add(pplr);*/
        }
        public static  Prefix GetPrefix(int prefixID) 
        {
            if (prefixID==ConfigUtils.config.DefaultPrefix.ID)
            {
                return ConfigUtils.config.DefaultPrefix;
            }
            if (prefixes.Exists(p => p.ID == prefixID))
            {
                return prefixes.Find(p => p.ID == prefixID);
            }
            else {
                return null;
            }
        }
        public static int GetMaxID(List<Prefix> prefixes) {
            int maxID = 0;
            foreach (var prefix in prefixes)
            {
                if (prefix.ID>maxID)
                {
                    maxID = prefix.ID;
                }
            }
            return maxID;
        }
    }
}
